/**
* @author   Frederic Saunier - www.tekool.net
* @since    2008/08/10
*
* Copyright (C) 2006 Frederic Saunier
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*
*/

package net.tekool.projects.objscomp.commands;

import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import net.tekool.projects.objscomp.business.ClassDescriptor;

public class ConcatenateCode
{
	private static String NEWLINE = System.getProperty("line.separator");
	private static String CLASS_PREFIX = "class_";
	
	private ArrayList<ClassDescriptor> classes;
	private StringBuilder code;
	
	/**
	 * Constructor
	 * 
	 * @param classes	The input classes list.
	 * @param code		The output code on which to append the generated code.
	 */
	public ConcatenateCode(ArrayList<ClassDescriptor> classes, StringBuilder code)
    {
	    super();
	    
	    this.classes = classes;
	    this.code = code;
    }
	
	/**
	 * Executes the command.
	 */
	public void execute()
	{	
		for( ClassDescriptor classDescriptor : classes )
		{
			String fileContent = classDescriptor.getFileContent();
			fileContent = stripMultilineComments(fileContent);
			fileContent = stripSingleLineComments(fileContent);
			fileContent = emptyWhiteLines(fileContent);
			fileContent = newlineToNewline(fileContent);
			fileContent = onlyOneNewline(fileContent);
			fileContent += NEWLINE+NEWLINE;
			
			code.append(fileContent);
		}
	}

	/**
	 * Remove all multiline comments in the file
	 */
	private String stripMultilineComments(String fileContent)
	{	
		//TODO We have to verify that the comment is not quoted.
		String regex = "/\\*.*?\\*/";
		Pattern pattern = Pattern.compile(regex, Pattern.DOTALL|Pattern.UNIX_LINES);
		Matcher matcher = pattern.matcher(fileContent); 
		return matcher.replaceAll("");
	}

	/**
	 * Remove all singleline comments in the file
	 */
	private String stripSingleLineComments(String fileContent)
	{		
		//TODO We have to verify that the comment is not quoted.
		String regex = "^\\s*?//.*$";
		Pattern pattern = Pattern.compile(regex, Pattern.UNIX_LINES|Pattern.MULTILINE);
		Matcher matcher = pattern.matcher(fileContent); 
		return matcher.replaceAll("");
	}

	/**
	 * Change all line separator types to the system default line separator.
	 */
	private String newlineToNewline(String fileContent)
	{
		String outStr = "";
		outStr = fileContent.replaceAll("\r", "");
		outStr = fileContent.replaceAll("\r\n", NEWLINE);
		return outStr;
	}

	/**
	 * Delete all the empty white lines.
	 */
	private String emptyWhiteLines(String fileContent)
	{
		String regex = "^\\s*$";
		Pattern pattern = Pattern.compile(regex, Pattern.UNIX_LINES|Pattern.MULTILINE);
		Matcher matcher = pattern.matcher(fileContent); 
		return matcher.replaceAll("");
	}
	
	/**
	 * Delete all duplicated new lines (more than one line separator following
	 * another is reduced to one line separator only).
	 */
	private String onlyOneNewline(String fileContent)
	{
		String regex = NEWLINE + "*";
		Pattern pattern = Pattern.compile(regex, Pattern.DOTALL|Pattern.UNIX_LINES);
		Matcher matcher = pattern.matcher(fileContent); 
		return matcher.replaceAll(NEWLINE);
	}
}